<?php

abstract class Model_Dec {

	protected $primary_key = "id";

	public function __construct() {}

	public static function factory($id=0,$model=null) {
		if(null==$model) $model = get_called_class();
		return new $model($id);
	}

	public function __call($method_name, $args) {
		if (preg_match('~^(set|get)([_])(.*)$~', $method_name, $matches)) {
			$property = $matches[3];
			if (!property_exists($this, $property)) {
				throw new Exception('Property ' . $property . ' not exists');
			}
			switch ($matches[1]) {
				case 'set':
					$this->check_arguments($args, 1, 1, $method_name);
					return $this->set($property, $args[0]);
				case 'get':
					$this->check_arguments($args, 0, 0, $method_name);
					return $this->get($property);
				case 'default':
					throw new Exception('Method ' . $method_name . ' not exists');
			}
		}
	}

	protected function get($property) {
		return $this->$property;
	}

	protected function set($property, $value) {
		$this->$property = $value;
		return $this;
	}

	private function check_arguments(array $args, $min, $max, $method_name) {
		$argc = count($args);
		if ($argc < $min || $argc > $max) {
			throw new Exception('Method ' . $method_name . ' needs minimaly ' . $min . ' and maximaly ' . $max . ' arguments. ' . $argc . ' arguments given.');
		}
	}
	
	protected function load($array) {
		foreach($array as $property=>$value){
			$this->set($property, $value);
		}
	}

	public function save() {
		if (false !== ($fields = $this->validate())) {
			if (!$this->get($this->primary_key)) {
				list($insertedId, $affectedRows) = DB::insert(constant(get_called_class() . "::TABLE"), array_keys($fields))->values(array_values($fields))->execute();
				$this->set_id($insertedId);
			} else {
				DB::update(constant(get_called_class() . "::TABLE"))->set($fields)->where($this->primary_key, "=", $this->get_id())->execute();
			}
			return $this->get_id();
		} else {
			return false;
		}
	}

	public function remove() {
		$db = db::delete(constant(get_called_class() . "::TABLE"))->where($this->primary_key, "=", $this->get($this->primary_key))->execute();
	}

	abstract public function validate();
	
} // End Dec